<template>
    <div class="file-upload">
        <div class="file-upload-container" @click.prevent="triggerUpload" v-bind="$attrs">
            <!-- 根据状态显示响应的效果 -->
            <slot v-if="fileStatus === 'loading'" name="loading">
                <button class="btn btn-primary">上传中...</button>
            </slot>
            <slot v-else-if="fileStatus === 'success'" name="uploaded" :uploadedData="uploadedData">
                <button class="btn btn-primary">上传成功</button>
            </slot>
            <slot v-else default>
                <button class="btn btn-primary">点击上传</button>
            </slot>
        </div>
        <input type="file" class="file-input d-none" ref="fileInput" @change="handFileChange">
    </div>
</template>

<script lang="ts">
import axios from 'axios'
import { PropType, defineComponent, ref, watch } from 'vue'

// 设置状态
// 准备上传 | 上传中 | 上传成功 | 上传失败
type UploadStatus = 'ready' | 'loading' | 'success' | 'error'
// 设置file的类型
type CheckFunction = (file: File) => boolean

export default defineComponent({
    props: {
        action: { type: String, required: true },
        beforeUpload: { type: Function as PropType<CheckFunction> },
        // 控制初始化---初始化File
        uploaded: {
            type: Object
        },
    },

    inheritAttrs: false, //
    // 定义成功和失败事件
    emits: ['file-uploaded', 'file-uploaded-error'],
    setup(props, context) {
        const fileInput = ref<null | HTMLInputElement>(null)
        // console.log(fileInput);

        // 声明状态
        const uploadedData = ref(props.uploaded)

        // 获取状态
        const fileStatus = ref<UploadStatus>(props.uploaded ? 'success' : 'ready')

        watch(() => props.uploaded, (newValue) => {      
            if (newValue) {
                fileStatus.value = 'success'
                uploadedData.value = newValue
            }
        })
        

        const triggerUpload = () => {
            if (fileInput.value) {
                fileInput.value.click() //给input绑定一个单击事件
            }
        }

        // 添加方法监听input的改变
        const handFileChange = (e: Event) => {
            const currentTarget = e.target as HTMLInputElement
            // console.log(currentTarget.files);

            if (currentTarget.files) {
                fileStatus.value = 'loading'
                const files = Array.from(currentTarget.files)
                // console.log(files);
                // console.log(files[0]);

                // 是否满足用户自定义的需求
                if (props.beforeUpload) {
                    const result = props.beforeUpload(files[0])
                    if (!result) {
                        return
                    }
                }

                // 发送表单数据，
                const formData = new FormData()
                // file--表单对应的名称
                formData.append('file', files[0])
                axios.post(props.action, formData, {
                    headers: {
                        "Content-Type": 'multipart/form-data'
                    }
                }).then((resp) => {
                    fileStatus.value = 'success'
                    uploadedData.value = resp.data
                    // 成功的时候触发
                    context.emit('file-uploaded', resp.data)
                }).catch((error) => {
                    fileStatus.value = 'error'
                    // 成功的时候触发
                    context.emit('file-uploaded-error', { error })
                }).finally(() => {
                    // 上传完毕把input设置成空值
                    if (fileInput.value) {
                        // 
                        fileInput.value.value = ''
                    }
                })


            }
        }
        return {
            fileStatus,
            fileInput,
            triggerUpload,
            handFileChange,
            uploadedData,
        }
    }
})
</script>

<style scoped></style>